#!coding:utf-8
# 1、python3.6和ansible2.7.8 api环境
# 2、封装ansible2.7.8 api
# author huangchengwu
import json
import shutil
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
import ansible.constants as C
from ansible.plugins.callback import CallbackBase
from ansible.executor.playbook_executor import PlaybookExecutor


class ResultCallback(CallbackBase):
    """
    重构输出
    """

    def __init__(self, *args, **kwargs):
        super(ResultCallback, self).__init__(*args, **kwargs)
        self.host_ok = {}
        self.host_unreachable = {}
        self.host_failed = {}

    def v2_runner_on_ok(self, result, **kwargs):
        """成功"""
        self.host_ok[result._host.name] = result._result["stdout"]

    def v2_runner_on_unreachable(self, result, **kwargs):
        """不可达"""
        self.host_unreachable[result._host.name] = result._result["msg"]

    def v2_runner_on_failed(self, result, ignore_errors=False, **kwargs):
        """失败"""
        self.host_failed[result._host.name] = result._result["stderr"]


class AnsibleApi():
    def __init__(self):
        self.Options = namedtuple('Options',
                                  ['connection',
                                   'module_path',
                                   'forks',
                                   'private_key_file',
                                   'remote_user',
                                   'become',
                                   'become_method',
                                   'become_user',
                                   'check',
                                   'diff'])
        self.ops = self.Options(connection='smart',
                                module_path=None,
                                forks=10,
                                private_key_file="/root/.ssh/id_rsa",
                                remote_user="root",
                                become=True,
                                become_method="sudo",
                                become_user="root",
                                check=False,
                                diff=False)
        self.loader = DataLoader()
        self.passwords = dict()
        self.inventory = InventoryManager(
            loader=self.loader, sources=['./tools/hosts'])
        self.callback = ResultCallback()

    def runner_playbook(self):
        variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory)
        pbex = PlaybookExecutor(playbooks=["./tools/p.yaml"],
                                inventory=self.inventory,
                                variable_manager=variable_manager,
                                loader=self.loader,
                                options=self.ops,
                                passwords=self.passwords)
        results = pbex.run()
        print(results)

    def add_host(self, group):
        for g in group:
            for _group, host_list in g.items():
                self.inventory.add_group(_group)
                for h in host_list:
                    self.inventory.add_host(
                        host=h["host"], port=h["port"], group=_group)
        print(self.inventory.get_groups_dict())

    def runner(self, hosts, module, args):

        # 加载之前的变量
        variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory)
        play_source = dict(
            name="Ansible Play",
            hosts=hosts,           # all表示匹配清单所有机器，看源码发现的
            gather_facts="no",
            tasks=[
                dict(action=dict(module=module, args=args), register='shell_out'),
            ]
        )
        play = Play().load(play_source, variable_manager=variable_manager, loader=self.loader)
        tqm = None
        try:
            tqm = TaskQueueManager(
                inventory=self.inventory,
                variable_manager=variable_manager,
                loader=self.loader,
                options=self.ops,
                passwords=self.passwords,
                stdout_callback=self.callback,
            )
            result = tqm.run(play)
            print(result)
        finally:
            if tqm is not None:
                tqm.cleanup()
            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

        result_raw = {'success': {}, 'failed': {}, 'unreachable': {}}
        for host, result in self.callback.host_ok.items():

            result_raw["success"][host] = result
        for host, result in self.callback.host_unreachable.items():

            result_raw['failed'][host] = result

        for host, result in self.callback.host_failed.items():

            result_raw['unreachable'][host] = result

        return json.dumps(result_raw, indent=4)


if __name__ == "__main__":
    # a = AnsibleApi()
    # a.add_host([
    #     {
    #         "test":[
    #             { "host": "172.16.0.169","port":22},
    #             { "host": "172.16.0.164","port":22},
    #         ]
    # }, {
    #         "hcw2":[
    #             { "host": "172.16.0.169","port":22},
    #             { "host": "172.16.0.164","port":22},
    #         ]
    # },

    # ])
    # data = a.runner("hcw2","shell", "echo 1")
    # print data

    #    an=AnsibleApi()
    # an.add_host([
    #         {
    #             "jenkins":[
    #                 { "host": "172.16.0.164","port":22},
    #             ]
    #     },
    #     ])
    # res = an.runner("jenkins","copy", "content='%s' dest=/root/hcw_test/check.sh mode=755 owner=root" % check_msg)
    # print res

    # res = an.runner("jenkins","copy", "content='%s' dest=/root/hcw_test/exec.sh mode=755 owner=root" % copy_msg)
    # print res

    # res = an.runner("jenkins","copy", "content='%s' dest=/root/hcw_test/build_msg.sh mode=755 owner=root" % build_msg)
    # print res
